//
// Created by hamlet on 23-3-12.
//

#include "Solver"
#include <iostream>
#include <fmt/core.h>
#include <mutex>
#include <thread>

namespace FansionML {
    LabelT Solver::predictAll(const DataT &data) {
        LabelT result{data.rows()};
        result.setConstant(-1);
        int sum = 0;
        std::mutex result_mutex;
        auto doJob = [this, &data, &result, &sum, &result_mutex](int id, int begin, int end) {
            fmt::print("线程{}：开始{}，结束{}\n", id, begin, end);
            for (int i = begin; i < end; ++i) {
                auto rs = predict(data.row(i));
                std::lock_guard<std::mutex> guard(result_mutex);
                result(i) = rs;
                ++sum;
                std::cout << '\r' << std::flush;
                fmt::print("进度：{:.2f}% 序号：{} 预测结果：{}        ", static_cast<double>(sum * 100) / data.rows(), i, rs);
            }
        };
        fmt::print("开始计算：\n线程分配情况：\n");
        std::vector<std::thread> threads;
        int amount = data.rows() / thread_num + 1, beg = 0, id = 0;
        while (true) {
            int end = beg + amount;
            if (end < data.rows()) {
                threads.emplace_back(doJob, ++id, beg, end);
            } else {
                threads.emplace_back(doJob, ++id, beg, data.rows());
                break;
            }
            beg = end;
        }
        for (auto &th: threads) {
            th.join();
        }
        std::cout << std::endl;
        return std::move(result);
    }

    void Solver::setThreadNum(int n) {
        thread_num = n;
    }
} // FansionML
